package qc.module.platform.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.ResourceStatusFlagEnum;
import qc.common.core.exception.QCPromptException;
import qc.common.core.tree.QCTreeNode;
import qc.common.core.tree.TreeDataDto;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.module.platform.dto.api.APIDto;
import qc.module.platform.dto.api.APIQueryConditionDto;
import qc.module.platform.dto.dept.DeptSimpleDto;
import qc.module.platform.dto.menu.MenuQueryConditionDto;
import qc.module.platform.dto.menu.MenuSimpleDto;
import qc.module.platform.dto.role.*;
import qc.module.platform.dto.user.UserQueryConditionDto;
import qc.module.platform.dto.user.UserSimpleInfoDto;
import qc.module.platform.entity.*;
import qc.module.platform.mapper.RolesMapper;
import qc.module.platform.repository.QcRoleRepository;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * RoleService
 *
 * @author QuCheng Tech
 * @create 2023/02/07
 */
@Service
public class RoleService {
    private QcRoleRepository repository;

    @Autowired
    public void setQcRoleRepository(QcRoleRepository repository) {
        this.repository = repository;
    }

    private RoleUserService roleUserService;

    @Autowired
    public void setRoleUserService(RoleUserService roleUserService) {
        this.roleUserService = roleUserService;
    }

    private RoleDeptService roleDeptService;

    @Autowired
    public void setRoleDeptService(RoleDeptService roleDeptService) {
        this.roleDeptService = roleDeptService;
    }

    private DeptUserService deptUserService;

    @Autowired
    public void setDeptUserService(DeptUserService deptUserService) {
        this.deptUserService = deptUserService;
    }

    private RoleMenuService roleMenuService;

    @Autowired
    public void setRoleMenuService(RoleMenuService roleMenuService) {
        this.roleMenuService = roleMenuService;
    }

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    private DeptService deptService;

    @Autowired
    public void setDeptService(DeptService deptService) {
        this.deptService = deptService;
    }

    private MenusService menusService;

    @Autowired
    public void setMenusService(MenusService menusService) {
        this.menusService = menusService;
    }

    private RoleResourceService roleResourceService;

    @Autowired
    public void setRoleResourceService(RoleResourceService roleResourceService) {
        this.roleResourceService = roleResourceService;
    }

    @Autowired
    private ApiService apiService;

    @Autowired
    private RoleApiService roleApiService;

    /**
     * 根据项目编号查询项目下所有角色
     *
     * @param dto 查询条件
     * @return 角色信息集合
     * @author QcCheng Tech
     * @since 2023/2/8
     */
    public List<RoleDto> query(RoleQueryConditionDto dto) throws Exception {
        if (dto == null)
            throw new QCPromptException("查询条件为空");
        if (StringUtils.isBlank(dto.getProject()))
            throw new QCPromptException("项目编码不能为空");
        LambdaQueryWrapper<QcRoles> wrapper = new LambdaQueryWrapper<>();
        //判断有无模糊查询 
        if (!StringUtils.isBlank(dto.getWords())) {
            wrapper.eq(QcRoles::getProjectcode, dto.getProject())
                    .like(QcRoles::getName, dto.getWords()).or().like(QcRoles::getDescription, dto.getWords());
        } else {
            wrapper.eq(QcRoles::getProjectcode, dto.getProject());
        }
        //排序
        wrapper.orderByAsc(QcRoles::getName);
        List<QcRoles> qcRoles = repository.selectList(wrapper);
        if (qcRoles != null && !qcRoles.isEmpty())
            return RolesMapper.MAPPER.toDtoList(qcRoles);
        return null;
    }

    /***
     * 获取指定项目中的所有角色，可以指定仅为有效状态或全部状态
     *
     * @param projectCode 项目编码
     * @param isValid 是否有效，true表示项目必须为有效状态，false表示不管项目状态是否有效
     * @return java.util.List<qc.module.platform.entity.QcRoles>
     * @author QuCheng Tech
     * @since 2023/8/30
     */
    public List<QcRoles> getProjectAllRoles(String projectCode, boolean isValid) {
        LambdaQueryWrapper<QcRoles> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QcRoles::getProjectcode, projectCode);
        if (isValid) {
            wrapper.eq(QcRoles::getFlag, ResourceStatusFlagEnum.NORMAL);
        }

        //排序
        wrapper.orderByAsc(QcRoles::getName);

        return repository.selectList(wrapper);
    }

    /***
     * 获取指定项目中指定用户关联的角色集合，可以指定仅为有效状态或全部
     *
     * @param projectCode 项目编码
     * @param userId 用户ID
     * @param isValid 是否有效，true表示项目必须为有效状态，false表示不管项目状态是否有效
     * @return java.util.List<qc.module.platform.entity.QcRoles>
     * @author QuCheng Tech
     * @since 2023/9/1
     */
    public List<QcRoles> getUserRoles(String projectCode, int userId, boolean isValid) {
        MPJLambdaWrapper<QcRoles> wrapper = new MPJLambdaWrapper<>();
        wrapper.select(QcRoles::getId, QcRoles::getProjectcode, QcRoles::getName, QcRoles::getFlag, QcRoles::getDescription);
        wrapper.innerJoin(QcRoleUser.class, QcRoleUser::getRoleid, QcRoles::getId);
        wrapper.eq(QcDeptUser::getUserid, userId);
        wrapper.eq(QcRoles::getProjectcode, projectCode);
        //是否仅为有效状态的部门
        if (isValid) wrapper.eq(QcRoles::getFlag, ResourceStatusFlagEnum.NORMAL);

        wrapper.orderByAsc(QcRoles::getName);

        return repository.selectJoinList(QcRoles.class, wrapper);
    }

    /**
     * 根据id查询角色
     *
     * @param id 角色id
     * @return 角色信息集合
     * @author QcCheng Tech
     * @since 2023/2/8
     */
    public RoleDto get(Integer id) throws Exception {
        QcRoles en = getEntity(id);
        if (en != null) {
            return RolesMapper.MAPPER.toDto(en);
        }

        return null;
    }

    /***
     * 获取指定ID的角色实体类
     *
     * @param roleId 角色ID
     * @return qc.module.platform.entity.QcRoles
     * @author QuCheng Tech
     * @since 2023/8/31
     */
    public QcRoles getEntity(int roleId) {
        return repository.selectById(roleId);
    }

    /**
     * 新增角色
     *
     * @param dto 角色信息
     * @return 成功返回null
     * @author QuCheng
     */
    public String add(RoleDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("对象不能为空");
        if (StringUtils.isBlank(dto.getName()))
            return QCUnifyReturnValue.Warn("角色名称不能为空");
        if (StringUtils.isBlank(dto.getPcode()))
            return QCUnifyReturnValue.Warn("项目编码不能为空");

        if (hasNameExist(dto.getName(), dto.getPcode(), 0x0))
            return QCUnifyReturnValue.Warn("当前项目下角色名称已存在!");

        //DTO转换为Entity
        QcRoles en = RolesMapper.MAPPER.RolesDtoToEntity(dto);

        //生成角色ID，获取数据库中的最大id+1后赋值
        en.setId(genereateId());

        if (repository.insert(en) < 0x1)
            return QCUnifyReturnValue.Warn("新增角色失败");
        return QCUnifyReturnValue.Success();
    }

    /**
     * 更新角色信息
     *
     * @param dto: 更新角色信息
     * @return String  成功返回null，失败返回错误信息
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    public String update(RoleDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("对象不能为空!");
        if (dto.getId() < 0x1)
            return QCUnifyReturnValue.Warn("角色ID不能为空");
        if (StringUtils.isBlank(dto.getName()))
            return QCUnifyReturnValue.Warn("角色名称不能为空!");
        if (StringUtils.isBlank(dto.getPcode()))
            return QCUnifyReturnValue.Warn("项目编码不能为空!");

        //判断修改的部门是否存在
        if (!hasIdExist(dto.getId()))
            return QCUnifyReturnValue.Warn("修改的角色ID不存在");
        //判断名称不能重复
        if (hasNameExist(dto.getName(), dto.getPcode(), dto.getId()))
            return QCUnifyReturnValue.Warn("当前项目下角色名称已存在!");

        //DTO转换为Entity
        QcRoles qcRoles = RolesMapper.MAPPER.RolesDtoToEntity(dto);

        repository.updateById(qcRoles);

        return QCUnifyReturnValue.Success();
    }

    /**
     * 判断角色是否存在，存在返回true
     *
     * @param id: 角色id
     * @return Boolean 角色存在返回true
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    boolean hasIdExist(int id) {
        LambdaQueryWrapper<QcRoles> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(QcRoles::getId);
        wrapper.eq(QcRoles::getId, id);
        QcRoles qcRoles = repository.selectOne(wrapper);
        if (qcRoles != null)
            return true;

        return false;
    }

    /**
     * 判断角色名称是否存在，存在返回true
     *
     * @param name: 角色名称
     * @return Boolean 角色存在返回true
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    boolean hasNameExist(String name, String projectCode, Integer id) {
        LambdaQueryWrapper<QcRoles> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(QcRoles::getId);
        wrapper.eq(QcRoles::getProjectcode, projectCode);
        wrapper.eq(QcRoles::getName, name);
        wrapper.ne(QcRoles::getId, id);

        QcRoles qcRoles = repository.selectOne(wrapper);
        if (qcRoles != null)
            return true;

        return false;
    }

    /**
     * 根据id逻辑删除角色
     *
     * @param id:           角色id
     * @param isLogicDelete 是否为逻辑删除
     * @return String 成功返回null,失败返回错误信息
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    public String delete(int id, boolean isLogicDelete) {
        if (!hasIdExist(id))
            return QCUnifyReturnValue.Warn("删除的角色ID不存在");

        if (isLogicDelete) {
            LambdaUpdateWrapper<QcRoles> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(QcRoles::getId, id).set(QcRoles::getFlag, ResourceStatusFlagEnum.DELETED);
            repository.update(null, lambdaUpdateWrapper);
        } else {
            //物理删除，同时删除关联关系
            roleMenuService.deleteByRoleId(id); //删除角色与菜单关联关系
            roleDeptService.deleteByRoleId(id); //删除角色与部门关联关系
            roleUserService.deleteByRoleId(id); //删除角色与用户的关联关系
            roleResourceService.deleteByRoleId(id);  //删除角色与资源的关联关系

            repository.deleteById(id);
        }

        return QCUnifyReturnValue.Success();
    }

    /**
     * 查询角色用户关系
     *
     * @param roleId: 角色id
     * @return List<RoleUserDto> 角色信息
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    public List<RoleUserDto> getRoleUsers(int roleId) throws QCPromptException {
        //查询当前角色项目编码
        QcRoles en = getEntity(roleId);
        if (en != null) {
            String projectCode = en.getProjectcode();
            //查询项目用户信息集合
            UserQueryConditionDto condition = new UserQueryConditionDto();
            condition.setProject(projectCode);

            List<UserSimpleInfoDto> userSimpleInfoDtos = userService.queryProjectUserSimple(condition);
            if (userSimpleInfoDtos != null && userSimpleInfoDtos.size() > 0x0) {
                //角色关联的用户取交集
                List<Integer> userIds = roleUserService.getUserIds(roleId);

                List<RoleUserDto> result = new ArrayList<>();

                for (UserSimpleInfoDto userSimpleInfoDto : userSimpleInfoDtos) {
                    boolean related = false;
                    if (userIds != null && userIds.size() > 0x0) {
                        if (userIds.contains((int) userSimpleInfoDto.getId())) {
                            related = true;
                        }
                    }
                    RoleUserDto dto = new RoleUserDto();
                    dto.setUser(userSimpleInfoDto);
                    dto.setChecked(related);
                    result.add(dto);
                }

                return result;
            }
        }

        return null;
    }

    /**
     * 设置角色用户关联关系
     *
     * @param dto: 角色用户关联关系
     * @return String 添加成功返回null，失败返回错误信息
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    public String setRoleUsers(RoleUserSetDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("传入的信息为空");

        int roleId = dto.getRoleid();
        QcRoles en = getEntity(roleId);
        if (en == null)
            return QCUnifyReturnValue.Warn("指定的角色信息错误或不存在");

        //先按角色ID删除已有的关联
        roleUserService.deleteByRoleId(roleId);
        //如果有设置关联用户ID信息，逐个进行添加
        if (dto.getUids() != null && dto.getUids().length > 0) {
            // 遍历dto.getUids()中的每个userid字符串
            for (String userid : dto.getUids()) {
                // 尝试将userid字符串转换为整数
                try {
                    int parsedUserId = Integer.parseInt(userid);
                    // 转换成功，添加关联关系
                    roleUserService.add(roleId, parsedUserId);
                } catch (NumberFormatException e) {
                    // 转换失败，跳过该字符串
                }
            }
        }
        return QCUnifyReturnValue.Success();
    }

    /**
     * 查询角色与菜单关联关系
     *
     * @param roleId: 角色id
     * @return List<RoleMenuDto> 角色菜单关系
     * @author QcCheng Tech
     * @date 2023/8/31
     */
    public List<RoleMenuDto> getRoleMenus(int roleId) throws QCPromptException {
        //查询当前角色项目编码
        QcRoles en = getEntity(roleId);
        if (en != null) {
            String projectCode = en.getProjectcode();
            //查询项目菜单集合
            MenuQueryConditionDto menuQueryCondition = new MenuQueryConditionDto();
            menuQueryCondition.setProject(projectCode);
            List<MenuSimpleDto> projectAllMenus = menusService.queryListSimple(menuQueryCondition);
            if (projectAllMenus != null && projectAllMenus.size() > 0x0) {
                //角色关联的菜单取交集
                List<Integer> menuIds = roleMenuService.getMenuIds(roleId);

                List<RoleMenuDto> result = new ArrayList<>();

                for (MenuSimpleDto menu : projectAllMenus) {
                    boolean related = false;
                    if (menuIds != null && menuIds.size() > 0x0) {
                        if (menuIds.contains((int) menu.getId())) {
                            related = true;
                        }
                    }
                    RoleMenuDto dto = new RoleMenuDto();
                    dto.setMenu(menu);
                    dto.setChecked(related);
                    result.add(dto);
                }

                return result;
            }
        }

        return null;
    }

    /**
     * 设置角色和菜单的关联关系
     *
     * @param dto: 关联关系
     * @return String 设置成功返回null,失败返回错误信息
     * @author QcCheng Tech
     * @date 2023/7/5
     */
    public String setRoleMenus(RoleMenuSetDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("传入的设置条件为空");

        int roleId = dto.getRoleid();
        QcRoles en = getEntity(roleId);
        if (en == null)
            return QCUnifyReturnValue.Warn("指定的角色信息错误或不存在");

        //先按角色ID删除已有的关联
        roleMenuService.deleteByRoleId(roleId);
        //如果有设置关联用户ID信息，逐个进行添加
        if (dto.getMids() != null && dto.getMids().length > 0x0) {
            for (int userid : dto.getMids()) {
                roleMenuService.add(roleId, userid);
            }
        }

        return QCUnifyReturnValue.Success();
    }

    /**
     * 查询角色与部门关联关系
     *
     * @param roleId: 角色id
     * @return List<RoleDeptDto> 角色部门关系
     * @author QcCheng Tech
     * @date 2023/8/31
     */
    public List<RoleDeptDto> getRoleDepts(int roleId) throws QCPromptException {
        //查询当前角色项目编码
        QcRoles en = getEntity(roleId);
        if (en != null) {
            String projectCode = en.getProjectcode();
            //查询项目部门集合
            List<DeptSimpleDto> projectAllDepts = deptService.querySimpleInfoList(projectCode, true, 0x0, false);
            if (projectAllDepts != null && projectAllDepts.size() > 0x0) {
                //角色关联的部门取交集
                List<Integer> deptIds = roleDeptService.getDeptIds(roleId);

                List<RoleDeptDto> result = new ArrayList<>();

                for (DeptSimpleDto dept : projectAllDepts) {
                    boolean related = false;
                    if (deptIds != null && deptIds.size() > 0x0) {
                        if (deptIds.contains((int) dept.getId())) {
                            related = true;
                        }
                    }
                    RoleDeptDto dto = new RoleDeptDto();
                    dto.setDept(dept);
                    dto.setChecked(related);
                    result.add(dto);
                }

                return result;
            }
        }

        return null;
    }

    /**
     * 设置角色和部门的关联关系
     *
     * @param dto: 关联关系
     * @return String 设置成功返回null,失败返回错误信息
     * @author QcCheng Tech
     * @date 2023/8/31
     */
    public String setRoleDepts(RoleDeptSetDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("传入的设置条件为空");

        int roleId = dto.getRoleid();
        QcRoles en = getEntity(roleId);
        if (en == null)
            return QCUnifyReturnValue.Warn("指定的角色信息错误或不存在");

        //先按角色ID删除已有的关联
        roleDeptService.deleteByRoleId(roleId);
        //如果有设置关联部门ID信息，逐个进行添加
        if (dto.getDids() != null && dto.getDids().length > 0x0) {
            for (int deptid : dto.getDids()) {
                roleDeptService.add(roleId, deptid);
            }
        }

        return QCUnifyReturnValue.Success();
    }

    /**
     * 生成记录ID，获取数据库表中的最大记录ID+1
     *
     * @return 生成记录ID
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    Integer genereateId() {
        Integer maxRecordId = getMaxId();
        return maxRecordId + 1;
    }

    /**
     * 获取数据库表中的最大ID值，没有记录时返回0
     *
     * @return 返回数据库表中的最大ID值
     * @author QuCheng Tech
     * @since 2023/5/28
     */
    Integer getMaxId() {
        LambdaQueryWrapper<QcRoles> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(QcRoles::getId);
        wrapper.orderByDesc(QcRoles::getId);
        QcRoles en = repository.selectOne(wrapper);
        if (en != null)
            return en.getId();

        return 0x0;
    }

    /**
     * 以树形结构返回结果，按部门的上下级关系列出所有部门；
     *
     * @param roleId: 角色id
     * @return TreeDataDto 返回结果集
     * @author QcCheng Tech
     * @date 2023/9/7
     */
    public TreeDataDto getRoleDeptsTree(int roleId) throws QCPromptException {
        // 查询当前角色的项目编码
        QcRoles roleEntity = getEntity(roleId);
        if (roleEntity == null) {
            return null;
        }
        String projectCode = roleEntity.getProjectcode();

        // 通过项目编码查询项目部门集合
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(projectCode, false);
        if (projectAllDepts == null || projectAllDepts.isEmpty()) {
            return null;
        }

        //构建返回结果集
        TreeDataDto result = new TreeDataDto();

        // 查询角色关联的部门
        List<Integer> deptIds = roleDeptService.getDeptIds(roleId);
        if (deptIds != null && !deptIds.isEmpty()) {
            List<String> checkedKeys = deptIds.stream().map(Object::toString).collect(Collectors.toList());
            result.setCheckedKeys(checkedKeys);
        }

        List<QCTreeNode> treeNodes = new ArrayList<>();
        // 获取一级部门
        List<QcDepts> level1Depts = projectAllDepts.stream().filter(dept -> dept.getParentid() == null || dept.getParentid().equals(0x0)).collect(Collectors.toList());

        for (QcDepts level1Dept : level1Depts) {
            QCTreeNode level1TreeNode = new QCTreeNode();
            level1TreeNode.setKey(String.valueOf(level1Dept.getId()));
            level1TreeNode.setTitle(level1Dept.getName());
            level1TreeNode.setLeaf(true);

            // 获取一级部门的下级部门
            List<QcDepts> level2Depts = projectAllDepts.stream().filter(dept -> dept.getParentid() != null && dept.getParentid().equals(level1Dept.getId())).collect(Collectors.toList());

            if (!level2Depts.isEmpty()) {
                level1TreeNode.setLeaf(false);
                List<QCTreeNode> level2TreeNodes = new ArrayList<>();
                for (QcDepts level2Dept : level2Depts) {
                    QCTreeNode level2TreeNode = new QCTreeNode();
                    level2TreeNode.setKey(String.valueOf(level2Dept.getId()));
                    level2TreeNode.setTitle(level2Dept.getName());
                    level2TreeNode.setLeaf(true);

                    // 获取二级部门的下级部门
                    List<QcDepts> level3Depts = projectAllDepts.stream().filter(dept -> dept.getParentid() != null && dept.getParentid().equals(level2Dept.getId())).collect(Collectors.toList());
                    if (!level3Depts.isEmpty()) {
                        level2TreeNode.setLeaf(false);
                        List<QCTreeNode> level3TreeNodes = new ArrayList<>();
                        for (QcDepts level3Dept : level3Depts) {
                            QCTreeNode level3TreeNode = new QCTreeNode();
                            level3TreeNode.setKey(String.valueOf(level3Dept.getId()));
                            level3TreeNode.setTitle(level3Dept.getName());
                            level3TreeNode.setLeaf(true);
                            // 可以继续获取四级节点

                            level3TreeNodes.add(level3TreeNode);
                        }
                        level2TreeNode.setChildren(level3TreeNodes);
                    }
                    level2TreeNodes.add(level2TreeNode);
                }
                level1TreeNode.setChildren(level2TreeNodes);
            }
            treeNodes.add(level1TreeNode);
        }

        result.setNodes(treeNodes);
        return result;
    }

    /**
     * 以树形结构返回结果，按菜单的上下级关系列出所有菜单；
     *
     * @param roleId: 角色id
     * @return TreeDataDto 返回结果集
     * @author QcCheng Tech
     * @date 2023/9/7
     */
    public TreeDataDto getRoleMenusTree(int roleId) throws QCPromptException {
        // 查询当前角色项目编码
        QcRoles en = getEntity(roleId);
        if (en == null) {
            return null;
        }

        String projectCode = en.getProjectcode();

        // 查询项目菜单集合
        List<QcMenus> projectAllMenus = menusService.getProjectAllMenus(projectCode);
        if (projectAllMenus == null || projectAllMenus.isEmpty()) {
            return null;
        }

        //构建返回结果集
        TreeDataDto result = new TreeDataDto();

        // 角色关联的菜单取交集
        List<Integer> menuIds = roleMenuService.getMenuIds(roleId);
        if (menuIds != null && !menuIds.isEmpty()) {
            List<String> checkedKeys = menuIds.stream().map(Object::toString).collect(Collectors.toList());
            result.setCheckedKeys(checkedKeys);
        }


        List<QCTreeNode> treeNodes = new ArrayList<>();

        // 获取一级菜单
        List<QcMenus> level1Menus = projectAllMenus.stream().filter(p -> p.getParentid() == null || p.getParentid().equals(0x0)).collect(Collectors.toList());

        for (QcMenus level1Menu : level1Menus) {
            QCTreeNode level1TreeNode = new QCTreeNode();
            level1TreeNode.setKey(String.valueOf(level1Menu.getId()));
            level1TreeNode.setTitle(level1Menu.getTitle());
            level1TreeNode.setLeaf(true);

            // 获取一级菜单的子菜单
            //List<QcMenus> subMenus = projectAllMenus.stream().filter(p -> p.getParentid() == level1Menu.getId()).collect(Collectors.toList());
            //2024-12-25，罗必好修改：父ID数据类型为Integer，包装类型不能使用==进行判断相同，需要修改为使用equals判断或判断intValue相等
            //问题参考：https://blog.csdn.net/rain_is_my_name/article/details/143708343
            List<QcMenus> subMenus = projectAllMenus.stream().filter(p -> p.getParentid() != null && p.getParentid().equals(level1Menu.getId())).collect(Collectors.toList());
            //List<QcMenus> subMenus = projectAllMenus.stream().filter(p -> p.getParentid().intValue() == level1Menu.getId().intValue()).collect(Collectors.toList());

            if (!subMenus.isEmpty()) {
                level1TreeNode.setLeaf(false);

                List<QCTreeNode> subTreeNodes = new ArrayList<>();
                for (QcMenus subMenu : subMenus) {
                    QCTreeNode subTreeNode = new QCTreeNode();
                    subTreeNode.setKey(String.valueOf(subMenu.getId()));
                    subTreeNode.setTitle(subMenu.getTitle());
                    subTreeNode.setLeaf(true);
                    // 可以继续获取子菜单的子菜单

                    subTreeNodes.add(subTreeNode);
                }
                level1TreeNode.setChildren(subTreeNodes);
            }

            treeNodes.add(level1TreeNode);
        }

        result.setNodes(treeNodes);

        return result;
    }

    /**
     * 以树形结构返回结果，树形结构一级节点为部门，二级节点为部门或部门中的用户；
     *
     * @param roleId: 角色id
     * @return TreeDataDto 返回结果集
     * @author QcCheng Tech
     * @date 2023/9/8
     */
    public TreeDataDto getRoleUsersTree(int roleId) {
        // 查询当前角色项目编码
        QcRoles roleEntity = getEntity(roleId);
        if (roleEntity == null) {
            return null;
        }
        String projectCode = roleEntity.getProjectcode();

        //构建返回结果集
        TreeDataDto result = new TreeDataDto();

        //查询角色关联的用户id集合
        List<Integer> userIds = roleUserService.getUserIds(roleId);
        if (userIds != null && !userIds.isEmpty()) {
            List<String> checkedKeys = userIds.stream().map(Object::toString).collect(Collectors.toList());
            result.setCheckedKeys(checkedKeys);
        }
        // 项目部门集合
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(projectCode, false);
        if (projectAllDepts == null || projectAllDepts.isEmpty()) {
            return null;
        }
        //查询所有项目用户集合
        UserQueryConditionDto conditionDto = new UserQueryConditionDto();
        conditionDto.setProject(projectCode);
        List<QcUsers> projectUsers = userService.queryProjectUsersList(conditionDto);

        // 通过项目部门id查询部门和用户的关联关系
        List<Integer> projectDeptsIds = projectAllDepts.stream()
                .map(QcDepts::getId)
                .collect(Collectors.toList());
        List<QcDeptUser> deptUserRelations = deptUserService.getEntityByDeptIds(projectDeptsIds);
        // 获取关联部门的用户ID集合
        List<Integer> userIdsInDept = deptUserRelations.stream().map(QcDeptUser::getUserid).collect(Collectors.toList());

        //构建树形结构返回
        List<QCTreeNode> treeNodes = new ArrayList<>();
        //生成一个根节点用于存放没有关联部门的用户
        QCTreeNode level1UserTreeNode = new QCTreeNode();
        level1UserTreeNode.setTitle("未关联部门用户");
        level1UserTreeNode.setIcon("ant-design:home-outlined");
        level1UserTreeNode.setLeaf(true);
        level1UserTreeNode.setKey("0");
        List<QCTreeNode> level2UsrsTreeNodes = new ArrayList<>();

        //去除关联部门的用户
        List<QcUsers> usersWithoutDepts = new ArrayList<>(projectUsers);
        usersWithoutDepts.removeIf(user -> userIdsInDept.contains(user.getId()));

        // 将没有关联部门的用户添加至结果集中
        if (usersWithoutDepts != null && !usersWithoutDepts.isEmpty()) {
            level1UserTreeNode.setLeaf(false);
            for (QcUsers users : usersWithoutDepts) {
                QCTreeNode level2UserTreeNode = new QCTreeNode();
                level2UserTreeNode.setKey(String.valueOf(users.getId()));
                level2UserTreeNode.setTitle(users.getName());
                level2UserTreeNode.setIcon("ant-design:user-outlined");
                level2UserTreeNode.setLeaf(true);
                level2UsrsTreeNodes.add(level2UserTreeNode);
            }
        }
        level1UserTreeNode.setChildren(level2UsrsTreeNodes);
        //将没有关联项目的用户添加至结果集中
        treeNodes.add(level1UserTreeNode);

        // 获取一级部门
        List<QcDepts> level1Depts = projectAllDepts.stream()
                .filter(dept -> dept != null && (dept.getParentid() == null || dept.getParentid().equals(0x0)))
                .collect(Collectors.toList());
        for (QcDepts level1Dept : level1Depts) {
            QCTreeNode level1TreeNode = new QCTreeNode();
            level1TreeNode.setKey(String.valueOf("dept" + "-" + level1Dept.getId()));
            level1TreeNode.setTitle(level1Dept.getName());
            level1TreeNode.setIcon("ant-design:home-outlined");
            level1TreeNode.setLeaf(true);

            //存储子树节点的列表，它是一个用于存放当前部门节点下的用户节点或下级部门节点
            List<QCTreeNode> level2TreeNodes = new ArrayList<>();
            //添加一级部门用户
            addUsersTreeNodes(deptUserRelations, level1TreeNode, projectUsers, level2TreeNodes);

            //获取二级部门
            List<QcDepts> level2Depts = projectAllDepts.stream()
                    .filter(dept -> dept.getParentid() != null && dept.getParentid().equals(level1Dept.getId()))
                    .collect(Collectors.toList());

            if (level2Depts != null && !level2Depts.isEmpty()) {
                level1TreeNode.setLeaf(false);
                for (QcDepts level2Dept : level2Depts) {
                    QCTreeNode level2TreeNode = new QCTreeNode();
                    level2TreeNode.setKey(String.valueOf("dept" + "-" + level2Dept.getId()));
                    level2TreeNode.setTitle(level2Dept.getName());
                    level2TreeNode.setIcon("ant-design:home-outlined");
                    level2TreeNode.setLeaf(true);
                    level2TreeNodes.add(level2TreeNode);

                    //存储子树节点的列表，它是一个用于存放当前部门节点下的用户节点或下级部门节点
                    List<QCTreeNode> level3TreeNodes = new ArrayList<>();
                    //添加二级部门用户
                    addUsersTreeNodes(deptUserRelations, level2TreeNode, projectUsers, level3TreeNodes);

                    //获取三级部门
                    List<QcDepts> level3Depts = projectAllDepts.stream()
                            .filter(dept -> dept.getParentid() != null && dept.getParentid().equals(level2Dept.getId()))
                            .collect(Collectors.toList());
                    if (level3Depts != null && !level3Depts.isEmpty()) {
                        level2TreeNode.setLeaf(false);
                        for (QcDepts level3Dept : level3Depts) {
                            QCTreeNode level3TreeNode = new QCTreeNode();
                            level3TreeNode.setKey(String.valueOf("dept" + "-" + level3Dept.getId()));
                            level3TreeNode.setTitle(level3Dept.getName());
                            level3TreeNode.setIcon("ant-design:home-outlined");
                            level3TreeNode.setLeaf(true);
                            level3TreeNodes.add(level3TreeNode);

                            //存储子树节点的列表，它是一个用于存放当前部门节点下的用户节点或下级部门节点
                            List<QCTreeNode> level4TreeNodes = new ArrayList<>();
                            //添加三级部门用户
                            addUsersTreeNodes(deptUserRelations, level3TreeNode, projectUsers, level4TreeNodes);

                            level3TreeNode.setChildren(level4TreeNodes);

                        }
                    }
                    level2TreeNode.setChildren(level3TreeNodes);
                }
            }
            level1TreeNode.setChildren(level2TreeNodes);
            treeNodes.add(level1TreeNode);
        }

        result.setNodes(treeNodes);
        return result;
    }


    /**
     * 为部门树形结构添加用户
     *
     * @param deptUserRelations:：部门和用户的关联关系列表。
     * @param treeNode:当前要处理的树节点对象。它代表了当前的部门节点。
     * @param projectUsers:项目中的用户列表。
     * @param childTreeNodes:存储子树节点的列表。它是一个用于存放当前部门节点下的用户节点的容器。
     * @author QcCheng Tech
     * @date 2023/9/11
     */
    private void addUsersTreeNodes(List<QcDeptUser> deptUserRelations, QCTreeNode treeNode, List<QcUsers> projectUsers, List<QCTreeNode> childTreeNodes) {
        //解析部门ID
        int deptId = Integer.parseInt(StringUtils.substringAfter(treeNode.getKey(), '-'));
        //获得当前部门和用户的关联关系
        List<QcDeptUser> filterDeptUserRelations = deptUserRelations.stream()
                .filter(deptUser -> deptUser.getDeptid().equals(deptId))
                .collect(Collectors.toList());

        if (filterDeptUserRelations != null && !filterDeptUserRelations.isEmpty()) {
            treeNode.setLeaf(false);
            //获取当前部门的用户id集合 
            List<Integer> userIdsForDept = filterDeptUserRelations.stream()
                    .map(QcDeptUser::getUserid)
                    .collect(Collectors.toList());
            //获得当前部门关联的用户集合
            List<QcUsers> deptUsers = projectUsers.stream()
                    .filter(user -> userIdsForDept.contains(user.getId()))
                    .collect(Collectors.toList());
            //添加当前部门用户
            if (deptUsers != null && !deptUsers.isEmpty()) {
                for (QcUsers qcUsers : deptUsers) {
                    QCTreeNode childTreeNode = new QCTreeNode();
                    childTreeNode.setKey(String.valueOf(qcUsers.getId()));
                    childTreeNode.setTitle(qcUsers.getName());
                    childTreeNode.setIcon("ant-design:user-outlined");
                    childTreeNode.setLeaf(true);
                    childTreeNodes.add(childTreeNode);
                }
            }
        }
    }

    /**
     * 获取角色API关联关系
     *
     * @param roleId 角色ID
     * @return List<RoleAPIDto>
     * @author QuCheng Tech
     * @since 2024/5/7
     */
    public List<RoleAPIDto> getRoleApis(Integer roleId) {

        List<RoleAPIDto> result = new ArrayList<>();

        //1.获取所有api列表集合
        APIQueryConditionDto conditionDto = new APIQueryConditionDto();
        List<APIDto> apiDtoList = apiService.query(conditionDto);

        if (CollectionUtils.isNotEmpty(apiDtoList)) {
            //2.获取角色关联api唯一标识集合
            List<String> apis = roleApiService.getApis(roleId);

            //3.设置返回结果集
            for (APIDto apiDto : apiDtoList) {
                boolean related = false;
                if (apis != null && apis.size() > 0x0) {
                    if (apis.contains(apiDto.getId())) {
                        related = true;
                    }
                }
                RoleAPIDto dto = new RoleAPIDto();
                dto.setApi(apiDto);
                dto.setChecked(related);
                result.add(dto);
            }
        }
        return result;
    }

    /**
     * 以树形结构返回结果，按Api接口分组分2级列出所有接口；
     *
     * @param roleId 角色id
     * @return TreeDataDto 返回结果集
     * @author QcCheng Tech
     * @date 2024/5/10
     */
    public TreeDataDto getRoleApisTree(Integer roleId) throws QCPromptException {
        if (roleId == null) throw new QCPromptException("角色ID不能为空");
        //1.构建返回结果集
        TreeDataDto result = new TreeDataDto();
        List<QCTreeNode> treeNodes = new ArrayList<>();

        //2.获取角色关联的api唯一标识集合
        List<String> roleApis = roleApiService.getApis(roleId);

        //3.设置结果集中角色已关联的api唯一标识
        if (CollectionUtils.isNotEmpty(roleApis)) {
            List<String> checkedKeys = roleApis.stream().map(Object::toString).collect(Collectors.toList());
            result.setCheckedKeys(checkedKeys);
        }

        //4.查询所有API信息集合
        List<APIDto> allApis = apiService.query(new APIQueryConditionDto());

        //5.查询所有API分组集合
        List<String> groups = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(allApis)) {
            //List<String> groupList = allApis.stream().map(map -> map.getApigroup()).collect(Collectors.toList());
            List<String> groupList = new ArrayList<>();
            for (APIDto apiDto : allApis) {
                if (StringUtils.isNotBlank(apiDto.getApigroup())) {
                    groupList.add(apiDto.getApigroup());
                } else {
                    groupList.add("未分组");
                    apiDto.setApigroup("未分组");
                }
            }
            groups = groupList.stream().distinct().collect(Collectors.toList());//去重
        }


        //6.将分组作为父级，子级为对应分组的api
        if (CollectionUtils.isNotEmpty(groups)) {
            for (String group : groups) {
                QCTreeNode level1TreeNode = new QCTreeNode();
                level1TreeNode.setKey(group);
                level1TreeNode.setTitle(group);
                level1TreeNode.setLeaf(true);

                //根据当前分组找出子节点api
                List<APIDto> subApis = allApis.stream().filter(p -> p.getApigroup().equals(group)).collect(Collectors.toList());
                if (!subApis.isEmpty()) {
                    level1TreeNode.setLeaf(false);

                    List<QCTreeNode> subTreeNodes = new ArrayList<>();
                    for (APIDto apiDto : subApis) {
                        QCTreeNode subTreeNode = new QCTreeNode();
                        subTreeNode.setKey(apiDto.getId());
                        subTreeNode.setTitle(apiDto.getName());
                        subTreeNode.setLeaf(true);
                        subTreeNodes.add(subTreeNode);
                    }
                    //结果按照key升序
                    level1TreeNode.setChildren(subTreeNodes.stream().sorted(Comparator.comparing(QCTreeNode::getKey)).collect(Collectors.toList()));
                }
                treeNodes.add(level1TreeNode);
            }
        }
        result.setNodes(treeNodes);

        return result;
    }

    /**
     * 设置角色API关联关系
     *
     * @param dto
     * @return 成功返回null，失败返回错误信息
     * @author QuCheng Tech
     * @since 2024/5/8
     */
    public String setRoleApis(RoleAPISetDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("传入的设置条件为空");

        int roleId = dto.getRoleid();
        QcRoles en = getEntity(roleId);
        if (en == null)
            return QCUnifyReturnValue.Warn("指定的角色信息错误或不存在");

        ////先按角色ID删除已有的关联
        roleApiService.deleteByRoleId(roleId);

        ////如果有设置关联API信息，逐个进行添加
        if (CollectionUtils.isNotEmpty(dto.getApis())) {
            for (String api : dto.getApis()) {
                //先判断api是否存在，不存在的不添加关联关系
                if (apiService.isExist(api)) {
                    roleApiService.add(roleId, api);
                }
            }
        }

        return QCUnifyReturnValue.Success();
    }

}